package com.wwu.system.service.impl;

import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wwu.common.utils.AssertUtil;
import com.wwu.common.web.ResultObj;
import com.wwu.common.redis.RedisConst;
import com.wwu.common.redis.RedisUtil;
import com.wwu.common.web.ResultPage;
import com.wwu.system.entity.SysParam;
import com.wwu.system.mapper.SysParamMapper;
import com.wwu.system.service.ISysParamService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;

/**
 * 参数配置服务实现类
 * @author 一蓑烟雨
 * @date 2023/5/31 9:39
 */
@Service
public class SysParamServiceImpl extends ServiceImpl<SysParamMapper, SysParam> implements ISysParamService {
    @Resource
    private RedisUtil redisUtil;

    /**
     * 分页查询参数配置
     * @param pageNum  页码
     * @param pageSize  每页数量
     * @param sysParam 参数配置
     * @return com.wwu.common.web.ResultPage<com.wwu.system.entity.SysParam>
     * @author 一蓑烟雨
     * @date 2023/7/1 11:30
     */
    @Override
    public ResultPage<SysParam> getParamListPage(Integer pageNum, Integer pageSize, SysParam sysParam) {
        Page<SysParam> page = new Page<>(pageNum,pageSize);
        LambdaQueryWrapper<SysParam> wrapper = new LambdaQueryWrapper<>();
        if(StringUtils.hasText(sysParam.getParamKey())){
            wrapper.like(SysParam::getParamKey,sysParam.getParamKey());
        }
        if(StringUtils.hasText(sysParam.getParamName())){
            wrapper.like(SysParam::getParamName,sysParam.getParamName());
        }
        if(!ObjectUtils.isEmpty(sysParam.getParamType())){
            wrapper.eq(SysParam::getParamType,sysParam.getParamType());
        }
        if(!ObjectUtils.isEmpty(sysParam.getParamStatus())){
            wrapper.eq(SysParam::getParamStatus,sysParam.getParamStatus());
        }
        wrapper.orderByAsc(SysParam::getParamKey);

        IPage<SysParam> sysParamPage = this.page(page, wrapper);
        return new ResultPage<>(sysParamPage);
    }

    /**
     * 根据参数键获取参数配置
     * @param paramKey  参数键
     * @return java.util.List<com.wwu.system.entity.SysParam>
     * @author 一蓑烟雨
     * @date 2023/7/1 10:50
     */
    @Override
    public SysParam getParamByKey(String paramKey) {
        AssertUtil.isTrue(!StringUtils.hasText(paramKey),"参数键不能为空");
        //从缓存中获取参数信息
        String sysParamJson = String.valueOf(redisUtil.getValue(RedisConst.Key.SYS_PARAM));
        List<SysParam> sysParamList = JSON.parseArray(sysParamJson).toList(SysParam.class);
        if(null != sysParamList){
            for (SysParam sysParam: (List<SysParam>)(List)sysParamList) {
                if(!ObjectUtils.isEmpty(sysParam) && paramKey.equals(sysParam.getParamKey())){
                    return sysParam;
                };
            }
        }

        //若缓存中不存在则查询数据库
        LambdaQueryWrapper<SysParam> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysParam::getParamKey,paramKey);

        return this.getOne(wrapper);
    }

    /**
     * 根据参数名获取参数配置
     * @param paramName
     * @return com.wwu.system.entity.SysParam
     * @author 一蓑烟雨
     * @date 2023/8/11 9:03
     */
    @Override
    public SysParam getParamByName(String paramName) {
        AssertUtil.isTrue(!StringUtils.hasText(paramName),"参数名不能为空");
        //从缓存中获取参数信息
        String sysParamJson = String.valueOf(redisUtil.getValue(RedisConst.Key.SYS_PARAM));
        List<SysParam> sysParamList = JSON.parseArray(sysParamJson).toList(SysParam.class);
        if(null != sysParamList){
            for (SysParam sysParam: (List<SysParam>)(List)sysParamList) {
                if(!ObjectUtils.isEmpty(sysParam) && paramName.equals(sysParam.getParamName())){
                    return sysParam;
                };
            }
        }

        //若缓存中不存在则查询数据库
        LambdaQueryWrapper<SysParam> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysParam::getParamName,paramName);

        return this.getOne(wrapper);
    }

    /**
     * 添加参数配置
     * @param sysParam 参数配置
     * @author 一蓑烟雨
     * @date 2023/8/11 9:06
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class)
    public void saveParam(SysParam sysParam) {
        AssertUtil.isTrue(!StringUtils.hasText(sysParam.getParamKey()),"参数key不能为空");
        SysParam sysParamTemp = this.getParamByKey(sysParam.getParamKey());
        AssertUtil.isTrue(null != sysParamTemp,"参数key已存在");

        AssertUtil.isTrue(!StringUtils.hasText(sysParam.getParamName()),"参数名不能为空");
        AssertUtil.isTrue(!StringUtils.hasText(sysParam.getParamValue()),"参数值不能为空");
        SysParam sysParamTemp1 = this.getParamByName(sysParam.getParamName());
        AssertUtil.isTrue(null != sysParamTemp1 && !sysParam.getParamKey().equals(sysParamTemp1.getParamKey()),"参数名已存在");

        AssertUtil.isTrue(!(this.save(sysParam)),"参数配置添加失败！");
        //更新缓存
        this.sysParamCache();
    }

    /**
     * 更新参数配置
     * @param sysParam 参数配置
     * @return com.wwu.common.web.ResultObj
     * @author 一蓑烟雨
     * @date 2023/5/30 18:34
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class)
    public ResultObj updateParam(SysParam sysParam) {
        AssertUtil.isTrue(!StringUtils.hasText(sysParam.getParamKey()),"参数key不能为空");

        AssertUtil.isTrue(!StringUtils.hasText(sysParam.getParamName()),"参数名不能为空");
        SysParam sysParamTemp1 = this.getParamByName(sysParam.getParamName());
        AssertUtil.isTrue(null != sysParamTemp1 && !sysParam.getParamKey().equals(sysParamTemp1.getParamKey()),"参数名已存在");

        //更新数据库
        AssertUtil.isTrue(!(this.updateById(sysParam)),"参数配置更新失败！");
        //更新缓存
        this.sysParamCache();

        return ResultObj.success();
    }

    /**
     * 更新参数配置状态
     * @param paramKey   参数key
     * @param paramStatus   参数状态
     * @author 一蓑烟雨
     * @date 2023/8/11 9:58
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class)
    public void updateParamStatus(String paramKey, Integer paramStatus) {
        AssertUtil.isTrue(!StringUtils.hasText(paramKey),"参数key不能为空");
        AssertUtil.isTrue(ObjectUtils.isEmpty(paramStatus),"参数状态不能为空");

        LambdaUpdateWrapper<SysParam> wrapper = new LambdaUpdateWrapper<>();
        wrapper.set(SysParam::getParamStatus,paramStatus)
                .eq(SysParam::getParamKey,paramKey);
        AssertUtil.isTrue(!this.update(wrapper),"参数配置状态更新失败！");
        //更新缓存
        this.sysParamCache();
    }

    /**
     * 删除参数配置
     * @param paramKeys  参数key集合
     * @author 一蓑烟雨
     * @date 2023/8/11 10:01
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class)
    public void deleteParam(List<String> paramKeys) {
        AssertUtil.isTrue(ObjectUtils.isEmpty(paramKeys),"参数key不能为空");
        AssertUtil.isTrue(!this.removeByIds(paramKeys),"参数配置删除失败！");
        //更新缓存
        this.sysParamCache();
    }

    /**
     * 查询参数配置，在项目启动时加载
     * @return com.wwu.common.web.ResultObj
     * @author 一蓑烟雨
     * @date 2023/7/20 16:14
     */
    @Override
    public ResultObj sysParamCache() {
        LambdaQueryWrapper<SysParam> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysParam::getParamStatus, 0)
                .orderByAsc(SysParam::getParamType)
                .orderByAsc(SysParam::getParamKey);

        List<SysParam> sysParamList = this.list(wrapper);
        //遍历系统字典，存储到缓存中
        if(!ObjectUtils.isEmpty(sysParamList)) {
            List<Object> objects = new ArrayList<>();
            objects.addAll(sysParamList);
            redisUtil.setValue(RedisConst.Key.SYS_PARAM, JSON.toJSONString(objects));
        }

        return ResultObj.success("参数配置缓存更新成功");
    }
}
